home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Shareware Grab Bag
/
Shareware Grab Bag.iso
/
050
/
madtrb13.arc
/
INT24.PAS
< prev
next >
Wrap
Pascal/Delphi Source File
|
1985-05-19
|
8KB
|
224 lines
{ Thanks to Marshall Brain for the original code for this routine.
Thanks to John Cooper for pointing out a small flaw in the code.
These routines provide a method for Turbo Pascal programs to trap MS-DOS
interrupt 24 (hex). INT 24 is called by DOS when a 'critical error' occurs,
and it normally prints the familiar "Abort, Retry, Ignore?" message.
With the INT 24 handler installed, errors of this type will be passed on to
Turbo Pascal as an error. If I/O checking is on, this will cause a program
crash. If I/O checking is off, IOResult will return an error code. The
global variable INT24Err will be true if an INT 24 error has occurred. The
variable INT24ErrorCode will contain the INT 24 error code as given by DOS.
These errors can be found in the DOS Technical Reference Manual. They
correspond to the error codes returned by the function INT24Result, with a
divisor of 256. INT24Result is used like IOResult, and calls IOResult. It
then checks INT24Err, and if it is true, returns INT24ErrorCode*256 instead.
In most cases, INT24Result should be used, because it does extra cleanup
(sets INT24Err back to false, and restores the INT 24 handler, since DOS
seems to sometimes reset the INT 24 vector after an error).
These routines are known to work correctly with: Turbo Pascal 2.00B PC-DOS;
Turbo Pascal 2.00B MS-DOS.
Note that Turbo's normal IOResult codes for MS-DOS DO NOT correspond to the
I/O error numbers given in Appendix I of the Turbo Pascal manual, or to the
error codes given in the I/O error nn, PC=aaaa/Program aborted message. Here
is a table of the correspondence (all numbers in hexadecimal):
IOResult Turbo error
-------- -------------------------------------------------
00 00 none
01 90 record length mismatch
02 01 file does not exist
03 F1 directory is full
04 FF file disappeared
05 02 file not open for input
06 03 file not open for output
07 99 unexpected end of file
08 F0 disk write error
09 10 error in numeric format
0A 99 unexpected end of file
0B F2 file size overflow
0C 99 unexpected end of file
0D F0 disk write error
0E 91 seek beyond end of file
0F 04 file not open
10 20 operation not allowed on a logical device
11 21 not allowed in direct mode
12 22 assign to standard files is not allowed
- Bela Lubkin
Borland International Technical Support
CompuServe 71016,1573
}
Const
INT24Err: Boolean=False;
INT24ErrCode: Byte=0;
OldINT24: Array [1..2] Of Integer=(0,0);
Var
RegisterSet: Record Case Integer Of
1: (AX,BX,CX,DX,BP,SI,DI,DS,ES,Flags: Integer);
2: (AL,AH,BL,BH,CL,CH,DL,DH: Byte);
End;
Procedure INT24;
Begin
{ To understand this routine, you will need to read
the description on Interrupt 24 in the DOS manual.
It also helps to examine the generated code under DEBUG. }
Inline
($2E/$C6/$06/ INT24Err /$01/$89/$EC/$83/$C4/$08/$89/$F8/$2E/$A2/
INT24ErrCode /$58/$B0/$FF/$5B/$59/$5A/$5E/$5F/$5D/$1F/$07/$CF);
{ Turbo: PUSH BP (Save caller's stack frame
MOV BP,SP Set up this procedure's stack frame
PUSH BP ?)
Inline: MOV BYTE CS:[INT24Err],1 Set INT24Err to True
MOV SP,BP Get correct SP; ADD: Discard saved
ADD SP,8 BP, INT 24 return address & flags
MOV AX,DI Get INT 24 error code
MOV CS:[INT24ErrCode],AL Save it in INT24ErrCode
POP AX Pop all registers
MOV AL,0FFH Set FCB call error flag:
POP BX will cause Turbo I/O error on file
POP CX operations, no error on character
POP DX operations
POP SI
POP DI
POP BP
POP DS
POP ES
IRET Return to next instruction }
End;
Procedure INT24On; { Enable INT 24 trapping }
Begin
INT24Err:=False;
With RegisterSet Do
Begin
AX:=$3524;
MsDos(RegisterSet);
If (OldINT24[1] Or OldINT24[2])=0 Then
Begin
OldINT24[1]:=ES;
OldINT24[2]:=BX;
End;
DS:=CSeg;
DX:=Ofs(INT24);
AX:=$2524;
MsDos(RegisterSet);
End;
End;
Procedure INT24Off; { Disable INT 24 trapping. Should be done at the end
of the program, if you plan to run the program from
within the Turbo compiler. If the INT 24 handler is
left in place, and the compiler gets a critical
error, the system is likely to crash. }
Begin
INT24Err:=False;
If OldINT24[1]<>0 Then
With RegisterSet Do
Begin
DS:=OldINT24[1];
DX:=OldINT24[2];
AX:=$2524;
MsDos(RegisterSet);
End;
OldINT24[1]:=0;
OldINT24[2]:=0;
End;
Function INT24Result: Integer;
Var
I:Integer;
Begin
I:=IOResult;
If INT24Err Then
Begin
I:=I+256*INT24ErrCode;
INT24On;
End;
INT24Result:=I;
End;
{ INT24Result returns all the regular Turbo IOResult codes if no critical
error has occurred. If a critical error, then the following values are
added to the error code from Turbo (each is 256 times the INT24ErrorCode
value returned by DOS):
256: Attempt to write on write protected disk
512: Unknown unit [internal dos error]
768: Drive not ready [drive door open or bad drive]
1024: Unknown command [internal dos error]
1280: Data error (CRC) [bad sector or drive]
1536: Bad request structure length [internal dos error]
1792: Seek error [bad disk or drive]
2048: Unknown media type [bad disk or drive]
2304: Sector not found [bad disk or drive]
2560: Printer out of paper [anything that the printer might signal]
2816: Write fault [character device not ready]
3072: Read fault [character device not ready]
3328: General failure [several meanings]
If you need the IOResult part, use
I:=INT24Result and 255; [masks out the INT 24 code]
For the INT 24 code, use
I:=INT24Result Shr 8; [same as Div 256, except faster]
INT24Result clears both error codes, so you must assign it to a variable if
you want to extract both codes:
J:=INT24Result;
WriteLn('Turbo IOResult = ',J And 255);
WriteLn('DOS INT 24 code = ',J Shr 8);
Note that in most cases, errors on character devices (LST and AUX) will not
return an IOResult, only an INT 24 error code. }
{ Main program. Delete next line to enable }
(*
{ Run this with printer off (or no printer), and nothing in drive A }
Var
F: File;
I: Integer;
Procedure PrinterTest;
Begin
WriteLn(LST,'test');
I:=INT24Result;
If I<>0 Then WriteLn('Printer error: ',I)
Else WriteLn('Printer OK');
End;
Procedure FileTest;
Begin
Assign(F,'A:FILE');
{$I-} Reset(F); {$I+}
I:=INT24Result;
If I<>0 Then WriteLn('Open failure on A:FILE : INT24Result=',I)
Else WriteLn('A:FILE exists');
Close(F);
End;
Begin
INT24On;
PrinterTest;
FileTest;
PrinterTest;
INT24Off;
FileTest;
PrinterTest;
End.
(**)